package org.mspring.platform.dao.query.criterion;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mspring.platform.dao.query.QueryBuilder;
import org.mspring.platform.dao.query.QueryHelper;
import org.mspring.platform.dao.query.criterion.inparam.Marshaller;
import org.mspring.platform.dao.query.criterion.inparam.MarshallerFactory;

/**
 * @author Gao Youbo
 * @since 2005-8-11
 */
public class InExpression implements Criterion {

    private static final long serialVersionUID = -7078800057194926430L;

    private static final Log log = LogFactory.getLog(InExpression.class);

    private String hqlName;
    private String paramKey;
    private Class<?> paramClass;

    protected InExpression(String hqlName, String paramKey, Class<?> paramClass) {
        this.hqlName = hqlName;
        this.paramKey = paramKey;
        this.paramClass = paramClass;
    }

    @Override
    public String toHqlString(QueryBuilder builder) {
        Object value = builder.getQueryParams().get(paramKey);
        if (log.isDebugEnabled()) {
            log.debug("Loading marshaller in InExpression for paramKey:" + paramKey + " with value:" + value);
        }
        Marshaller marshaller = MarshallerFactory.createMarshaller(value);
        log.debug("Using " + marshaller + " in InExpression.");

        if (!marshaller.hasValues()) {
            return null;
        }

        builder.getNamedQueryParams().put(QueryHelper.qualifyHql(hqlName), marshaller.getNamedQueryParamValue(paramClass));
        builder.getValidQueryParams().put(paramKey, marshaller.stringValue());

        // use hqlName as query parameter name e.g. user.id in (:user.id)
        return new StringBuilder().append(hqlName).append(" in (").append(":").append(QueryHelper.qualifyHql(hqlName)).append(")").toString();
    }

}
